/**
 * Copyright (c) Martijn Grootens (m.e.grootens@student.utwente.nl), 
 * University of Twente.
 * Created july 2012.
 *
 * This file is part of dbcleaner.
 * 
 * dbcleaner is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * dbcleaner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with dbcleaner.  If not, see <http://www.gnu.org/licenses/>.
 */

package dbcleaner.core.parse;
import dbcleaner.core.dbentries.*;
import dbcleaner.core.tags.*;
import java.util.*;
import java.io.*;

/**
 * Utils for reading the BibTeX database file.
 */
public class DataBaseFactory {

    /**
     * Create a DataBase with Entries from the given Scanner.
     */
    public static DataBase read_input_file (Scanner in_db) {
        
        DataBase db = new DataBase();
        
        // A newly read line and its first character.
        String ln;
        char first_char;
        
        // The class of the Entry and its contents
        String entry_class = "";
        String entry_contents = "";
        
        // Are we still reading the contents of an entry? Is the closing
        // bracket of the Entry read yet?
        boolean is_entry_content = true;
        boolean is_entry_finished = false;
        
        // Parse file
        while (in_db.hasNextLine()) {
            
            // Fetch new line
            ln = in_db.nextLine();
            
            // Assume it contains the contents of an Entry that is not closed.
            is_entry_content = true;
            is_entry_finished = false;
            
            // If line is not_empty (else just whitespace; skip).
            if (ln.length()>0) {
                
                // Fetch first character and switch.
                first_char = ln.charAt(0);
                
                switch (first_char) {
                    case '%': 
                        // It is a comment; ignore.
                        is_entry_content = false;
                        break;
                        
                    case '@': 
                        // It is a new entry; so no contents.
                        // Fetch the name of the BibTeX class and set the new
                        // contents to empty.
                        is_entry_content = false;
                        entry_class = cut_out_class_name(ln);
                        entry_contents = "";
                        break;
                        
                    case '}': 
                        // This MIGHT be the end of entry
                        // but only if nothing more is following..!
                        // (we assume a line of whitespace after each entry.)
                        if (ln.equals("}")) {
                            is_entry_content = false;
                            is_entry_finished = true;
                        }
                        break;
                        
                    case '\t':
                        // Indentation by a tab; cut it off.
                        ln = ln.substring(1);
                        break;
                        
                    case ' ':
                        // Indentation by (hopefully) 4 spaces; cut it off.
                        ln = ln.substring(4);
                        break;
                        
                    default : 
                        break;
                }
                
            }
            
            if (is_entry_content) {
                // We read contents of the reference; append.
                entry_contents += ln + "\n";
            }
            else if (is_entry_finished) {
                // We have obtained the class name and the contents of the BibTeX
                // reference, so parse and add the newly obtained Entry.
                Entry e = EntryFactory.get_entry(entry_class, entry_contents);
                db.add_entry(e);
            }
            
        }
        return db;
    }
    
    /**
     * Cut class name out of "@foo{bar,\n".
     */
    private static String cut_out_class_name (String ln) {
        
        int cut_l = 1;
        int cut_r = ln.indexOf('{');
        
        return ln.substring(cut_l,cut_r);
        
    }

}